package com.pan.lock;

import lombok.extern.slf4j.Slf4j;

import java.util.Stack;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author by panstark
 * @description
 * @notice
 * @date 2021/4/30
 */
@Slf4j
public class ReetrantLockDemo2 {

    /**
     * 锁对象
     */
    final Lock lock = new ReentrantLock();
    /**
     * 写线程条件 
     */
    final Condition notFull = lock.newCondition();
    /**
     * 读线程条件
     */
    final Condition notEmpty = lock.newCondition();

    /**
     * 缓存队列
     */
    final Stack<String> items =  new Stack<>();
    /**
     * count队列中存在的数据个数
     */
    int count;

    public void put(String value) throws InterruptedException {
        lock.lock();
        try {
             //假设队列只能放1000个
            if (items.size() >= 1000) {

                log.info("notFull等待状态{}",Thread.currentThread().getName());
                //阻塞写线程
                notFull.await();
            }else{
                items.push(value);
                count++;
                log.info("notEmpty进行signal{},写入的值为{}",Thread.currentThread().getName(),value);
                notEmpty.signal();//唤醒读线程
            }
        } finally{
            lock.unlock();
        }
    }

    public Object take() throws InterruptedException {
        lock.lock();
        try {
            if (items.isEmpty()) {//如果队列为空


                log.info("notEmpty等待状态{}",Thread.currentThread().getName());
                notEmpty.await();//阻塞读线程
            }
            Object value = items.pop();//取值 
            log.info("notFull进行signal{}",Thread.currentThread().getName());
            count--;
            notFull.signal();//唤醒写线程
            return value;

        } finally{
            lock.unlock();
        }
    }

    public static void main(String[] args) {
        ReetrantLockDemo2 reetrantLockDemo2 = new ReetrantLockDemo2();
        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    for (int i = 0; i <1000 ; i++) {
                        if(i%10==0){
                            Thread.sleep(500);
                            for (int j = 0; j <10 ; j++) {
                                Object take = reetrantLockDemo2.take();
                                log.info("take:{}",take);
                            }
                        }
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });

        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    for (int i = 0; i < 2000; i++) {
                        //Thread.sleep(1000);
                        reetrantLockDemo2.put("i:"+i);
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });

        t1.start();
        t2.start();
    }
}